<?php

namespace App\Jobs;

use App\Models\Order;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Support\Str;

/**
 * 发货回调 2020-12-15 21:52:08 后来取消订单也是走的这里
 * Class PromotionJob
 * @package App\Jobs
 */
class DeliveryCallbackJob extends Job
{
    private $order;

    public function __construct($order)
    {
        $this->order = $order;
    }

    public function handle()
    {
        try {
            $postData = [
                'courier_information' => $this->order['courier_information'] ?? [], // 发货信息
                'status' => $this->order['status'] ?? Order::STATUS_TO_BE_DELIVERED, // 状态
                'timestamp' => Carbon::now()->timestamp,
                'nonce' => Str::random(6),
            ];
            $postData['signature'] = $this->getSign($postData);
            $postData = json_encode($postData);

            $res = (new Client())->request('POST', $this->order['delivery_callback'], [
                'timeout' => 3,
                'allow_redirects' => false,
                'json' => $postData
            ]);

            \Log::info(sprintf('[SDK] 回调通知: %s 参数: %s 返回: %s', $this->order['delivery_callback'], $postData, $res->getBody()->getContents() ?? '[]'));

            $resStatusCode = $res->getStatusCode();
            $isFailed = !(200 <= $resStatusCode && $resStatusCode < 300);
            if ($isFailed) {
                throw new \HttpException('返回 status code 不在成功范围内(' . $resStatusCode . ')');
            }
        } catch (\Exception $e) {
            if ($this->attempts() < 3) {
                \Log::alert('发货回调进入重试阶段(' . $this->attempts() . '):' . $e->getMessage());
                $this->release($this->attempts() * (2 * 60));
            } else {
                \Log::alert('发货回调重试次数超限,结束回调(订单:' . $this->order['numbering'] . ')');
            }
        }
    }

    private function getSign($params = [])
    {
        $formatBizQueryParaMap = static function ($paramsMap) use (&$formatBizQueryParaMap) {
            $buff = [];
            ksort($paramsMap);
            foreach ($paramsMap as $k => $v) {
                if (is_array($v)) {
                    $buff = array_merge($buff, $formatBizQueryParaMap($v));
                } else {
                    $buff[] = $v;
                }
            }

            return $buff;
        };

        return strtolower(md5(implode('&', $formatBizQueryParaMap($params)) . config('auth.sdk_secret')));
    }
}
